import { createStore } from "redux";

const store = createStore(fn); //createStore 函数接受另一个函数作为参数，返回新生成的Store对象

//Store对象包含所有数据。如果想要督导某个时点的数据，就要对Store生成快照。这个时点的集合就叫做State。
const state = store.getState();

//State的变化，会导致View的变化。用户只能接触到View，所以，State的变化必须是View导致的。Action就是View发出的通知，标实State应该要发生变化了
//Action是对象。type属性必须，表示Action的名称。其他属性可以自由设置。
const action = {
  type: "ADD_TODO", //名称
  payload: "learn redux" //携带的信息
};

//Action Creator --一个被定义，来生成Action的函数
const ADD_TODO = "添加 TODO";
function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  };
}
const action = addTodo("learn Redux");

//store.dispatch()  --View 发出Action的唯一方法
store.dispatch({
  type: "ADD_TODO",
  payload: "learn redux"
});

//Reducer --Store收到Action后，必须给出一个新的state，这样View才会发生变化。这种State的计算过程叫做Reducer
//store.dispatch方法会出发Reducer自动执行
//需要 在生成Store时，将Reducer传入createStore中
//Reducer 是一个纯函数
//eg：
//State是一个对象
function reducer(state, action) {
  return Object.assign({}, state, { thingToChange });
  //or
  return { ...state, ...newState };
}

//State是一个数组
function reducer(state, action) {
  return [...state, newItem];
}

//store.subscribe()
//Store允许使用store.subscribe方法设置舰艇函数，一旦State发生变化，自动执行该函数
//store.subscribe方法返回一个函数，调用这个函数可以解除监听

//store.getState()
//store.dispatch()
//store.subscribe()
import { createStore } from "redux";
const { getState, dispatch, subscribe } = createStore(reducer);

//Reducer拆分
//combineReducers 方法，将各个子Reducer函数，合并成一个大的Reducer
import { combineReducers } from "redux";

//写法一：State的属性名与Reducer同名
const reducer = combineReducers({
  reducer1,
  reducer2,
  reducer3
});
//写法二：State的属性名与Reducer不同名
const resucer = combineReducers({
  a: reducer1,
  b: reducer2
});
export default todoApp;

//可以将所有的子Reducer放在一个文件里面，然后统一引入
import { combineReducers } from "redux";
import * as reducers from "./reducers";
const reducer = combineReducers(reducers);

//中间件  --对store.dispatch 方法进行改造，在发出Action和执行Reducer这两步之间，添加其他功能的  函数
//常用的现有中间件，可以引用别人的模板
//中间件 -- redux-logger
import { applyMiddleware, createStore } from "redux";
import createLogger from "redux-logger"; //一个redux的中间件
const logger = createLogger();
const store = createStore(reducer, applyMiddleware(logger));

//中间件 -- redux-thunk  -- 异步操作
//改造store.dispatch，是的store.dispatch可以接受函数作为参数
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducer from "./reducers";
//Note:this API requires redux@>=3.1.0
const store = createStore(reducer, applyMiddleware(thunk));

//中间件 -- redux-promise  -- 一部解决方案
import { createStore, applyMiddleware } from "redux";
import promiseMiddleware from "redux-promise";
import reducer from "./reducers";
const store = createStore(reducer, applyMiddleware(promiseMiddleware));

// React-Redux  -- 在react中使用redux  也可以自主用 redux
// React-Redux 将组件分为两大类： UI组件 和 容器组件
// UI组件-- 负责UI 的 呈现
// 容器组件 -- 负责管理数据和逻辑

// connect（） -- 用于从UI组件生成容器组件
// 建立一个从（外部的）state对象到（UI 组件的）props对象的映射关系
// 执行后应该返回一个对象
// mapStateToProps会订阅 Store，每当state更新的时候，就会自动执行，重新计算 UI 组件的参数，从而触发 UI 组件的重新渲染
// mapStateToProps的第一个参数总是state对象，还可以使用第二个参数，代表容器组件的props对象。
import { connect } from "react-redux";
const VisibleTodoList = connect(
  mapStateToProps, // 负责UI组件的业务逻辑 --输入逻辑
  mapDispatchToProps // 负责UI组件的业务逻辑 --输出逻辑 ， 将用户对UI组件的操作映射成Action
)(TodoList);

//<Provider>组件 --让容器组件拿到 state
import { Provider } from "react-redux";
import { createStore } from "redux";
import todoApp from "./reducers";
import App from "./components/App";
let store = createStore(todoApp);
//Provider 在根组件外面包了一层，这样一来，App的所有子组件就默认都可以拿到state
//原理是 React 的 context 属性
render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

// 使用 React-Router 路由库 的 项目
const Root = ({ store }) => (
  <Provider store={store}>
    <Router>
      <Route path="/" component={App} />
    </Router>
  </Provider>
);
